﻿using IM.Easy.Entity.Scheduled;
using IM.Easy.ScheduledServices.IServices;
using IM.Easy.ScheduledServices.Services;
using Quartz;
using Quartz.Listener;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IM.Easy.ScheduledServices.Listener
{
    public class JobListener : JobListenerSupport
    {
        public override string Name => "JobListener";

        private readonly IJobExecutionHistoryService jobLogService;
        private readonly IScheduledJobService scheduledJobService;
        public JobListener(IJobExecutionHistoryService jobLogService, IScheduledJobService scheduledJobService)
        {
            this.jobLogService = jobLogService;
            this.scheduledJobService = scheduledJobService;
        }

        public override Task JobWasExecuted(IJobExecutionContext context, JobExecutionException? jobException, CancellationToken cancellationToken = default)
        {
            var jobId = Guid.TryParse(context.JobDetail.Key.Name, out var parsedJobId) ? parsedJobId : Guid.Empty;
            var triggerId = Guid.TryParse(context.Trigger.Key.Name, out var parsedTriggerId) ? parsedTriggerId : Guid.Empty;
            var log = new JobExecutionHistory
            {
                JobId = jobId,
                TriggerId = triggerId,
                StartTime = context.FireTimeUtc.LocalDateTime,
                EndTime = DateTime.Now,
                Duration = (long)context.JobRunTime.TotalMilliseconds,
                Success = jobException == null,
                ErrorMessage = jobException?.GetBaseException().Message,
                FireInstanceId = context.FireInstanceId,
            };
            jobLogService.Create(log);
            UpdateJob(context);
            return Task.CompletedTask;
        }

        private void UpdateJob(IJobExecutionContext context)
        {
            try
            {
                var job = scheduledJobService.GetById(context.JobDetail.Key.Name);

                if (!IsSingle(context.Trigger))
                {
                    job.NextFireTime = context.NextFireTimeUtc?.LocalDateTime;
                }
                job.LastFireTime = context.FireTimeUtc.LocalDateTime;
                job.FireCount += 1;
                scheduledJobService.Update(job);
            }
            catch
            {
                Console.WriteLine("未能正常更新相关数据");
            }
        }


        /// <summary>
        /// 判断是否单独执行计划
        /// </summary>
        /// <param name="trigger"></param>
        /// <returns></returns>
        private bool IsSingle(ITrigger trigger)
        {
            var match = trigger.JobDataMap.TryGetBoolean("single", out bool single);
            return match && single;
        }
    }

}
